package com.zhangqiancheng.wcdmaconsole;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * 模拟设备工作，用于测试App工作是否正常。
 * <ul>
 * <li>设备开始向固定端点发送UDP心跳包（暂定192.168.1.101:5071）</li>
 * <li>设备从5070端口接收命令，目前有以下命令：
 * <ul>
 * <li>参数设置：0301MCC:460@MNC:01@LAC:2345@ARFCNo:39@PSC:12@RAC:2@，回应成功：03020，回应失败：03021</li>
 * <li>开启监听：0001，回应：00020成功，00021失败</li>
 * <li>关停监听：0004，回应：00050成功，00051失败</li>
 * </ul>
 * </li>
 * <li>设备向固定端点发送上报数据，目前有：
 * <ul>
 * <li>设备状态上报，每10秒一次：0309ID#0 关停，0309ID#1 运行</li>
 * <li>设备上报：0324IMSI#IMEI#GSM类型#</li>
 * </ul>
 * </ul>
 */
public class WcdmaUdpWatcher {

	static boolean turnedOn = false;
	static boolean settingsOk = false;
	static boolean settings2GOk = false;
	private static String host = "qczhang-PC";
	private static int sendPort = 5071;
	private static int receivePort = 5070;
	private static boolean reporting;

	private static String[][] stubWatchList = {
			{ "1234", "1234" },
			{ "1357", "1357" },
			{ "1024", "1024" },
			{ "2345", "2345" },
			{ "9999", "9999" }
	};

	/**
	 * @param args
	 * @throws SocketException
	 *             , IOException
	 */
	public static void main(String[] args) throws SocketException, IOException {

		// TODO 启动监听 5070 端口，用于接收命令，5071 端口用于发送心跳包、上报数据等内容
		DatagramSocket udpServer = new DatagramSocket(receivePort);
		byte[] buf = new byte[1024];
		DatagramPacket packet = new DatagramPacket(buf, buf.length);

		startHeartBeating(udpServer);

		while (true) {
			udpServer.receive(packet);
			// System.out.println(new String(packet.getData(), packet.getOffset(), packet.getLength()));
			WcdmaRequest request = WcdmaRequest.parse(packet);
			
			System.out.println("receive: " + request.toString());

			processAndRespond(udpServer, request);
		}
	}

	private static void startHeartBeating(final DatagramSocket udpServer) {

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (true) {

					String message = turnedOn ? "03091234#1" : "03091234#0";
					System.out.println("send heartbeating: " + message);
					byte[] buf = message.getBytes();
					DatagramPacket packet;
					try {
						packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(host), sendPort);
						udpServer.send(packet);
					}
					catch (IOException ex) {
						ex.printStackTrace();
					}

					try {
						Thread.sleep(10 * 1000); // 10秒发一次
					}
					catch (InterruptedException e) {
						e.printStackTrace();
					}

				}

			}
		}).start();

	}

	private static void processAndRespond(final DatagramSocket udpServer, final WcdmaRequest request) {

		new Thread(new Runnable() {

			@Override
			public void run() {

				try {
					switch (request.getTypeAndProtocol()) {
					case "0001":
						turnOnAndRespond(udpServer);
						break;
					case "0004":
						turnOffAndRespond(udpServer);
						break;
					case "0301":
						updateSettingsAndRespond(udpServer);
						break;
					case "0614":
						update2GAndRespond(udpServer);
						break;
					}
				}
				catch (IOException ex) {
					ex.printStackTrace();
				}
			}

		}).start();

	}

	private static void turnOnAndRespond(final DatagramSocket udpServer) throws IOException,
			UnknownHostException {

		WcdmaResponse response = new TurnOnResponse("0");
		udpServer.send(response.toPacket(InetAddress.getByName(host), sendPort));
		if (!turnedOn)
			turnedOn = true;
	}

	private static void turnOffAndRespond(final DatagramSocket udpServer) throws IOException,
			UnknownHostException {

		WcdmaResponse response = new TurnOffReponse("0");
		System.out.println("response: " + response.toString());
		udpServer.send(response.toPacket(InetAddress.getByName(host), sendPort));
		if (turnedOn)
			turnedOn = false;
	}

	private static void updateSettingsAndRespond(final DatagramSocket udpServer) throws IOException {

		// TODO update device settings
		if (!settingsOk) {
			settingsOk = true;
			checkSettingsAndWatch(udpServer);
		}
		// send response
		WcdmaResponse response = new SettingsResponse("0");
		System.out.println("response: " + response.toString());
		udpServer.send(response.toPacket(InetAddress.getByName(host), sendPort));
	}

	private static void update2GAndRespond(final DatagramSocket udpServer) throws IOException {

		// TODO update 2G settings
		if (!settings2GOk) {
			settings2GOk = true;
			checkSettingsAndWatch(udpServer);
		}
		// send response
		WcdmaResponse response = new Setting2GResponse("0");
		System.out.println("response: " + response.toString());
		udpServer.send(response.toPacket(InetAddress.getByName(host), sendPort));
	}

	private static void checkSettingsAndWatch(final DatagramSocket udpServer) {

		if (!settingsOk || !settings2GOk)
			return;
		
		if (reporting)
			return;

		new Thread(new Runnable() {

			@Override
			public void run() {

				while (turnedOn) {
					
					try {
						Thread.sleep(10 * 1000); // 隔10秒上报一次
					}
					catch (InterruptedException e1) {
						e1.printStackTrace();
					} 
					
					int n = (int) (Math.random() * 10) % stubWatchList.length;
					String imsi = stubWatchList[n][0];
					String imei = stubWatchList[n][1];

					WcdmaResponse watchReport = new WatchReport(imsi, imei, "0000");
					System.out.println("response: " + watchReport.toString());
					try {
						udpServer.send(watchReport.toPacket(InetAddress.getByName(host), sendPort));
					}
					catch (UnknownHostException e) {
						e.printStackTrace();
					}
					catch (IOException e) {
						e.printStackTrace();
					}
				}
				
				reporting = false;
			}
		}).start();

	}

}
